﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AG.Editor.Core.Data;
using System.Xml.Linq;
using System.IO;
using AG.Editor.Core;
using AG.Editor.Core.Metadata;

namespace AG.Editor.ModelUI.Windows
{
    public partial class AGImportModelWindow : Form
    {
        public AGModel ImportedModel { get; private set; }
        private string _modelFileFolder;
        private string _modelFilePath;
        private string _modelFolderPath;
        private string _modelFileName;

        public AGImportModelWindow()
        {
            InitializeComponent();

            _ctlTextCategoryInfo.Visible = false;
            _ctlListModelCategory.DataSource = AGEContext.Current.EProject.TProject.ModelCategories;
            _ctlListModelCategory.SelectedItem = null;
            _ctlListModelCategory.Enabled = false;
        }

        private void _ctlBtnBrowse_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    FileInfo file = new FileInfo(dlg.FileName);
                    _modelFilePath = dlg.FileName;
                    _modelFileFolder = file.Directory.FullName;
                    _modelFileName = file.Name.Replace(file.Extension, string.Empty);
                    _modelFolderPath = string.Format("{0}\\{1}\\", file.Directory.FullName, _modelFileName);

                    ImportedModel = ConverToModel(dlg.FileName);

                    ImportedModel.Category = AGEContext.Current.EProject.TProject.GetModelCategory(ImportedModel.CategoryId);

                    _ctlBtnBrowse.Text = ImportedModel.ToString();
                    if (ImportedModel.Category == null)
                    {
                        _ctlTextCategoryInfo.Text = "此模型还没有类别的定义，请选择正确的类别";
                        _ctlTextCategoryInfo.Visible = true;
                        _ctlListModelCategory.SelectedItem = null;
                        _ctlListModelCategory.Enabled = true;
                    }
                    else
                    {
                        _ctlTextCategoryInfo.Visible = false;
                        _ctlListModelCategory.SelectedItem = ImportedModel.Category;
                        _ctlListModelCategory.Enabled = false;
                    }
                }
                catch
                {
                    ImportedModel = null;
                }
            }
        }

        private void _ctlBtnOK_Click(object sender, EventArgs e)
        {
            if (ImportedModel == null || _ctlListModelCategory.SelectedItem == null)
            {
                return;
            }

            AGModelCategory selCategory = _ctlListModelCategory.SelectedItem as AGModelCategory;
            if (ImportedModel.Category == null)
            {
                if (!MatchModelToCategory(ImportedModel, selCategory))
                {
                    MessageBox.Show("导入的模型结构和所选择的的模型类别中的结构不一致，请确认类别是否选择正确?", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                ImportedModel.CategoryId = selCategory.Id;
                ImportedModel.Category = selCategory;
            }

            // 拷贝文件到项目所在目录
            MoveFiles(ImportedModel);

            MessageBox.Show("导入成功!");
            DialogResult = System.Windows.Forms.DialogResult.OK;
        }

        private AGModel ConverToModel(string modelFile)
        {
            XDocument xDoc = XDocument.Load(modelFile);
            XElement xModel = xDoc.Element("model");
            int modelId = Convert.ToInt32(xModel.Attribute("id").Value);
            string modelCaption = xModel.Attribute("caption").Value;

            AGModel model = new AGModel();
            model.Id = modelId;
            model.Caption = modelCaption;

            XAttribute xAttrCategory = xModel.Attribute("category-id");
            if (xAttrCategory != null)
            {
                model.CategoryId = Convert.ToInt32(xAttrCategory.Value);
            }

            List<XElement> xActionList = xModel.Elements("action").ToList();
            for (int index = 0; index < xActionList.Count; index++)
            {
                XElement xAction = xActionList[index];
                LoadAction(model, xAction);
            }
            return model;
        }

        private void LoadAction(AGModel model, XElement xAction)
        {
            int actionId = Convert.ToInt32(xAction.Attribute("id").Value);
            AGAction action = new AGAction(actionId);
            model.Actions.Add(action);
            action.Model = model;

            List<XElement> xDirList = xAction.Elements("direction").ToList();
            for (int index = 0; index < xDirList.Count; index++)
            {
                XElement xDir = xDirList[index];
                LoadDirection(action, xDir);
            }
        }

        private void LoadDirection(AGAction action, XElement xDir)
        {
            int dirId = Convert.ToInt32(xDir.Attribute("id").Value);
            AGDirection direction = new AGDirection(dirId);
            action.Directions.Add(direction);
            direction.Action = action;

            List<XElement> xFrameList = xDir.Elements("frame").ToList();
            for (int index = 0; index < xFrameList.Count; index++)
            {
                XElement xFrame = xFrameList[index];
                LoadFrame(direction, xFrame);
            }
        }

        private void LoadFrame(AGDirection directon, XElement xFrame)
        {
            //<frame id="0" rect="0,0,850,480" pivot="0,0" path="0499/0499-00-00-00" />
            int frameId = Convert.ToInt32(xFrame.Attribute("id").Value);
            string strRect = xFrame.Attribute("rect").Value;
            string[] strRectArr = strRect.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            string strPivot = xFrame.Attribute("pivot").Value;
            string[] strPivotArr = strPivot.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            string strPath = xFrame.Attribute("path").Value;

            if (strPath.StartsWith("Data/"))
            {
                strPath = strPath.Replace("Data/", string.Empty);
            }
            if (strPath.StartsWith("Data\\"))
            {
                strPath = strPath.Replace("Data\\", string.Empty);
            }

            if (strPath.StartsWith("Models/"))
            {
                strPath = strPath.Replace("Models/", string.Empty);
            }
            if (strPath.StartsWith("Models\\"))
            {
                strPath = strPath.Replace("Models\\", string.Empty);
            }

            if(strPath.StartsWith(string.Format("{0}/",_modelFileName)))
            {
                strPath = strPath.Replace(string.Format("{0}/", _modelFileName), string.Empty);
            }

            if (strPath.StartsWith(string.Format("{0}\\", _modelFileName)))
            {
                strPath = strPath.Replace(string.Format("{0}\\", _modelFileName), string.Empty);
            }

            AGFrame frame = new AGFrame();
            frame.Id = frameId;
            frame.Width = Convert.ToInt32(strRectArr[2]) - Convert.ToInt32(strRectArr[0]);
            frame.Height = Convert.ToInt32(strRectArr[3]) - Convert.ToInt32(strRectArr[1]);
            frame.AnchorPointX = Convert.ToInt32(strPivotArr[0]);
            frame.AnchorPointY = Convert.ToInt32(strPivotArr[1]);
            frame.ImageFileName = string.Format("{0}.png", strPath); //string.Format("{0}/{1}.png", _modelFileFolder, strPath);
            directon.AddFrame(frame);
        }

        private void MoveFiles(AGModel model)
        {
            string destDataFolder = AGEContext.Current.EProject.GetFolderData();
            string destModelFolder = string.Format("{0}{1}\\", AGEContext.Current.EProject.GetFolderModels(), model.UniqueId);
            
            if (!Directory.Exists(destModelFolder))
            {
                Directory.CreateDirectory(destModelFolder);
            }

            AGTools.Current.ModelStore.SaveModel(AGEContext.Current.EProject, model);

            for (int actionIndex = 0; actionIndex < model.Actions.Count; actionIndex++)
            {
                AGAction action = model.Actions[actionIndex];
                for (int dirIndex = 0; dirIndex < action.Directions.Count; dirIndex++)
                {
                    AGDirection direction = action.Directions[dirIndex];
                    for (int frameIndex = 0; frameIndex < direction.Frames.Count; frameIndex++)
                    {
                        AGFrame frame = direction.Frames[frameIndex];
                        string srcFrameFile = string.Format("{0}{1}", _modelFolderPath, frame.ImageFileName);
                        string destFrameFile = string.Format("{0}{1}", destModelFolder, frame.ImageFileName);
                        File.Copy(srcFrameFile, destFrameFile);
                    }
                }
            }
        }

        private bool MatchModelToCategory(AGModel model, AGModelCategory category)
        {
            if (category.Actions.Count != model.Actions.Count)
            {
                return false;
            }

            if (model.Actions[0].Directions.Count != AGDirectionModeParse.ToInt(category.DirectionMode))
            {
                return false;
            }

            for (int actionIndex = 0; actionIndex < model.Actions.Count; actionIndex++)
            {
                AGAction modelAction = model.Actions[actionIndex];
                AGAction categoryAction = category.Actions[actionIndex];
                modelAction.Caption = categoryAction.Caption;

                for (int dirIndex = 0; dirIndex < modelAction.Directions.Count; dirIndex++)
                {
                    AGDirection direction = modelAction.Directions[dirIndex];
                    AGDirection cDirection = categoryAction.Directions[dirIndex];
                    direction.Caption = cDirection.Caption;
                }
            }
            return true;
        }
    }
}
